/*
 * ProcessCANBus.cpp
 *
 *  Created on: Jul 8, 2011
 *      Author: matthew
 */

#include "ProcessCANBus.h"

int main(int argc, char *argv[])
{
	FILE *fpSource, *fpDest;
	char strReadBuff[256],
		 strHeaderLine[256],
		 strSourceFile[256],
		 strFileBase[256],
		 strFileName[256],
		 strID[256],
		 strData[256],
		 *pFileName,
		 *pFileNameNext;
	float fStartTime = -1;
	CA4CANBusData CBData;

	// Clear terminal screen on *nix systems
	printf("\033[2J");

	// Open the CANBus data source file
	if ((fpSource = fopen(argv[1], "r")) == NULL)
	{
		printf("Could not open file %s\n", argv[1]);
		exit(1);
	}

	strcpy(strSourceFile, argv[1]);
	// Get file name base (portion before '.extension')
	strFileBase[0] = 0;
	pFileName = strtok(argv[1], ".\r\n");
	strcpy(strFileBase, pFileName);
	pFileName = strtok(NULL, ".\r\n");
	pFileNameNext = strtok(NULL, ".\r\n");

	while (pFileNameNext != NULL)
	{
		strcat(strFileBase, ".\r\n");
		strcat(strFileBase, pFileName);
		pFileName = pFileNameNext;
		pFileNameNext = strtok(NULL, ".\r\n");
	}

//	printf("Filename base is %s\n",strFileBase);

	// Read the header line
	if (!feof(fpSource))
		fgets(strHeaderLine, 256, fpSource);
	else
	{
		printf("File too short, no header line.\n");
		exit(1);
	}

	printf("\n\nLoading CAN bus data from %s...\n", strSourceFile);

	// Read in the rest of the file data
	while (!feof(fpSource))
	{
		// Read the next line of data
		if (fgets(strReadBuff, 256, fpSource))
		{
//			printf("Line: %s.\n",strReadBuff);
			float fTime = atof(strtok(strReadBuff, " ,\t\r\n"));
			if (fStartTime < 0)
				fStartTime = fTime;
//			printf("%f ",fTime);
			strcpy(strID, strtok(NULL, " ,\t\r\n"));
//			printf("%s ", strID);
			if (strcmp(strID, "005") == 0)
				printf("%f %s\n", fTime, strID);
			strcpy(strData, strtok(NULL, " ,\t\r\n"));
			strcpy(strData, strtok(NULL, "\t\r\n"));
//			printf("%s\n", strData);

			// Store the data
			CBData.AddRawData(strID, fTime, strData);
//			printf("'%f %s %s'\n",fTime, strID, strData);
//			printf("Collected %d IDs.\n", CBData.GetNumIDs());
		}
	}

	// Done with source file
	fclose(fpSource);

//	printf("Number of IDs collected: %d\n", CBData.GetNumIDs());

	printf("Processing CAN bus data...\n");

	// Adjust and format CAN bus data
	for (unsigned int nCounter = 0; nCounter < CBData.GetNumIDs(); nCounter++)
	{
		float fLast = 0,
			  fThis = 0;
		int nMinutes = 0,
		    nIndex = 0;

		while (nIndex < CBData.GetNumDataEntriesForIndex(nCounter))
		{
			if (nIndex == 0)
				fLast = 0;
			else
				fLast = fThis;

			fThis = CBData.GetTimestamp(nCounter, nIndex);

			if (fThis < fLast)
				nMinutes++;

			CBData.SetTimestamp(nCounter, nIndex, CBData.GetTimestamp(nCounter, nIndex) - fStartTime + 60 * nMinutes);

			nIndex++;
		}
	}

	printf("\nWriting CAN Bus data (HEX) out to .tsv formatted files...\n\n");

	// Write out CAN bus data to file
	for (int nCounter = 0; nCounter < CBData.GetNumIDs(); nCounter++)
	{
		// Generate the file name for this file
		strcpy(strFileName, strFileBase);
		strncat(strFileName, "-hex-", 5);
		strncat(strFileName, CBData.GetID(nCounter).c_str(), CBData.GetID(nCounter).length());
		strncat(strFileName, ".tsv\0", 5);

		printf("\tWriting ID %s to %s...\n", CBData.GetID(nCounter).c_str(), strFileName);

		// Open the CANBus data destination file
		if ((fpDest = fopen(strFileName, "w")) == NULL)
		{
			printf("Could not open file %s for writing.\n", strFileName);
			exit(1);
		}

		fprintf(fpDest, "%s", strHeaderLine);

		for (int nInnerCounter = 0; nInnerCounter < CBData.GetNumDataEntriesForIndex(nCounter); nInnerCounter++)
		{
			fprintf(fpDest, "%f\t%s%s\n", CBData.GetTimestamp(nCounter, nInnerCounter),
					CBData.GetID(nCounter).c_str(),
					CBData.GetRawDataHexString(nCounter, nInnerCounter).c_str());
		}

		fclose(fpDest);
	}

	printf("\nWriting CAN Bus data (DEC) out to .tsv formatted files...\n\n");

	// Write out CAN bus data to file
	for (int nCounter = 0; nCounter < CBData.GetNumIDs(); nCounter++)
	{
		// Generate the file name for this file
		strcpy(strFileName, strFileBase);
		strncat(strFileName, "-dec-", 5);
		strncat(strFileName, CBData.GetID(nCounter).c_str(), CBData.GetID(nCounter).length());
		strncat(strFileName, ".tsv\0", 5);

		printf("\tWriting ID %s to %s...\n", CBData.GetID(nCounter).c_str(), strFileName);

		// Open the CANBus data destination file
		if ((fpDest = fopen(strFileName, "w")) == NULL)
		{
			printf("Could not open file %s for writing.\n", strFileName);
			exit(1);
		}

		fprintf(fpDest, "%s", strHeaderLine);

		for (int nInnerCounter = 0; nInnerCounter < CBData.GetNumDataEntriesForIndex(nCounter); nInnerCounter++)
		{
			fprintf(fpDest, "%f\t%s%s\n", CBData.GetTimestamp(nCounter, nInnerCounter),
					CBData.GetID(nCounter).c_str(),
					CBData.GetRawDataDecString(nCounter, nInnerCounter).c_str());
		}

		fclose(fpDest);
	}

	printf("\nGenerating data fields for CAN Bus data...\n\n");
	CA4CANDataFields DataFields;
	CBData.PopulateWithDataFields(&DataFields);

	printf("Writing CAN Bus data (data fields) out to .tsv formatted files...\n\n");

	// Write out CAN bus data to file
	for (int nCounter = 0; nCounter < DataFields.GetNumIDs(); nCounter++)
	{
		// Generate the file name for this file
		strcpy(strFileName, strFileBase);
		strncat(strFileName, "-data_fields-", 13);
		strncat(strFileName, DataFields.GetID(nCounter).c_str(), DataFields.GetID(nCounter).length());
		strncat(strFileName, ".tsv\0", 5);

		printf("\tWriting ID %s to %s...\n", DataFields.GetID(nCounter).c_str(), strFileName);

		// Open the CANBus data destination file
		if ((fpDest = fopen(strFileName, "w")) == NULL)
		{
			printf("Could not open file %s for writing.\n", strFileName);
			exit(1);
		}

		fprintf(fpDest, "%s", strHeaderLine);

		for (int nInnerCounter = 0; nInnerCounter < DataFields.GetNumDataEntriesForIndex(nCounter); nInnerCounter++)
		{
			fprintf(fpDest, "%f\t%s%s\n", DataFields.GetTimestamp(nCounter, nInnerCounter),
					DataFields.GetID(nCounter).c_str(),
					DataFields.GetRawDataDecString(nCounter, nInnerCounter).c_str());
		}

		fclose(fpDest);
	}

	printf("\nWriting CAN Bus data (individual data fields) out to .tsv formatted files...\n\n");

	// Write out CAN bus data to file
	// Loop through each stored ID
	for (int nCounter = 0; nCounter < DataFields.GetNumIDs(); nCounter++)
	{
		// Loop through each data field within the current ID
		for (int nFieldNum = 0; nFieldNum < DataFields.GetData(nCounter, 0).size(); nFieldNum++)
		{
			// Write out file containing one data field from one ID

			// Generate the file name for this file
			strcpy(strFileName, strFileBase);
			strncat(strFileName, "-data fields-", 13);
			strncat(strFileName, DataFields.GetID(nCounter).c_str(), DataFields.GetID(nCounter).length());
			char strFieldNum[256];
			sprintf(strFieldNum, "-%d",nFieldNum);
			strncat(strFileName, strFieldNum, strlen(strFieldNum));
			strncat(strFileName, ".tsv\0", 5);

			printf("\tWriting ID %s Field %d to %s... (%d lines)\n", DataFields.GetID(nCounter).c_str(), nFieldNum, strFileName, DataFields.GetNumDataEntriesForIndex(nCounter));

			// Open the CANBus data destination file
			if ((fpDest = fopen(strFileName, "w")) == NULL)
			{
				printf("Could not open file %s for writing.\n", strFileName);
				exit(1);
			}

			// fprintf(fpDest, "%s", strHeaderLine);

			for (int nInnerCounter = 0; nInnerCounter < DataFields.GetNumDataEntriesForIndex(nCounter); nInnerCounter++)
			{
				fprintf(fpDest, "%f\t%d\n", DataFields.GetTimestamp(nCounter, nInnerCounter),
						DataFields.GetData(nCounter, nInnerCounter).at(nFieldNum));
			}

			fclose(fpDest);
		}

	}

	printf("\nDone.\n\n");

	return 0;
}

